####
#
# Copyright 2007 B. Chandler Carruth
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
####
#
# ./lib/rcons/util
#
# This file provides a module for detecting changes to a file through
# digesting.
#
####

require( 'digest/sha2' )
require( 'pathname' )

require( 'rcons/environment' )

module RCons
  module FileChangeModule
    def has_digest( file )
      file = Pathname.expand_path( @build_env.expand( file ) )

      path = @build_env.expand( @scratch_path )
      @build_env.mkdir_p( path ) unless File.directory?( path )

      if File.readable?( File.join( path, 'digests' ) )
        IO.foreach( File.join( path, 'digests' ) ) do |l|
          if l =~ /\A#{file}(?!\\) \w+\Z/
            return( true )
          end
        end
      end

      return( false )
    end

    def update_digest( file )
      path = @build_env.expand( @scratch_path )
      @build_env.mkdir_p( path ) unless File.directory?( path )

      digest_hash = {}
      if File.readable?( File.join( path, 'digests' ) )
        IO.foreach( File.join( path, 'digests' ) ) do |l|
          l.scan( /(\A.+)(?!\\) (\w+)\Z/ ) do |f,h|
            digest_hash[ f ] = h
          end
        end
      end

      file = File.expand_path( @build_env.expand( file ) )

      return false unless File.readable?( file )

      digest = Digest::SHA256.new()
      chunk = ''

      File.open( file, 'rb' ) do |f|
        digest << chunk while f.read( 4096, chunk )
      end

      digest_hash[ file ] = digest

      File.open( File.join( path, 'digests' ), File::TRUNC | File::CREAT | File::WRONLY ) do |f|
        for fn, h in digest_hash
          f.puts( "#{fn} #{h}" )
        end
      end
    end

    def check_digest( file )
      file = File.expand_path( @build_env.expand( file ) )

      return false unless File.readable?( file )

      digest = Digest::SHA256.new()
      chunk = ''

      File.open( file, 'rb' ) do |f|
        digest << chunk while f.read( 4096, chunk )
      end

      path = @build_env.expand( @scratch_path )
      @build_env.mkdir_p( path ) unless File.directory?( path )

      if File.readable?( File.join( path, 'digests' ) )
        IO.foreach( File.join( path, 'digests' ) ) do |l|
          l.scan( /\A#{file} (\w+)\Z/ ) do |h|
            if h.to_s() == digest.to_s()
              return( true )
            end
          end
        end
      end

      return( false )
    end
  end
end

